#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Odoo JSON-RPC Client - Read Hostel Students
从 Odoo 服务器读取 hostel.student 模型的数据
"""

import json
import urllib.request
import urllib.parse
import ssl

# Odoo 服务器配置
ODOO_URL = "https://naturedao.tech"
API_KEY = "298a4b1128cb1bdb8da2bb87e0e9c11e9b82850f"
DATABASE = "odootest"  # 数据库名称
USERNAME = "yan.gao@ccwin-in.com"  # API Key 对应的用户名

# 创建忽略 SSL 验证的上下文（如果需要）
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE


def json_rpc(url, method, params):
    """
    执行 JSON-RPC 调用
    
    Args:
        url: Odoo 服务器 URL
        method: RPC 方法名
        params: 方法参数
    
    Returns:
        dict: 响应结果
    """
    data = {
        "jsonrpc": "2.0",
        "method": method,
        "params": params,
        "id": 1,
    }
    
    req = urllib.request.Request(
        url=url,
        data=json.dumps(data).encode('utf-8'),
        headers={
            "Content-Type": "application/json",
        }
    )
    
    try:
        response = urllib.request.urlopen(req, context=ssl_context)
        result = json.loads(response.read().decode('utf-8'))
        
        if 'error' in result:
            raise Exception(result['error'])
        
        return result.get('result')
    
    except urllib.error.HTTPError as e:
        print(f"HTTP 错误: {e.code} - {e.reason}")
        print(f"响应内容: {e.read().decode('utf-8')}")
        raise
    except Exception as e:
        print(f"请求错误: {str(e)}")
        raise


def authenticate():
    """
    使用 API Key 进行身份验证
    
    Returns:
        int: 用户 ID
    """
    print("正在进行身份验证...")
    print(f"  URL: {ODOO_URL}/jsonrpc")
    print(f"  数据库: {DATABASE}")
    print(f"  用户名: admin")
    print(f"  API Key: {API_KEY[:20]}...{API_KEY[-10:]}")
    
    # 使用 API Key 进行验证
    result = json_rpc(
        f"{ODOO_URL}/jsonrpc",
        "call",
        {
            "service": "common",
            "method": "authenticate",
            "args": [DATABASE, "admin", API_KEY, {}]
        }
    )
    
    print(f"  认证结果: {result}")
    
    if result:
        print(f"✓ 身份验证成功！用户 ID: {result}")
        return result
    else:
        print("✗ 身份验证失败")
        print("  提示：请检查 API Key 是否正确，或尝试在 Odoo 中重新生成 API Key")
        raise Exception("身份验证失败")


def search_read_students(uid, password):
    """
    读取 hostel.student 模型的数据
    
    Args:
        uid: 用户 ID
        password: API Key
    
    Returns:
        list: 学生记录列表
    """
    print("\n正在读取学生数据...")
    
    # 定义要读取的字段
    fields = [
        'id',
        'name',
        'gender',
        'class_id',
        'room_id',
        'hostel_id',
        'check_in_date',
        'check_out_date',
        'stay_duration',
        'status',
        'active',
    ]
    
    # 调用 search_read 方法
    students = json_rpc(
        f"{ODOO_URL}/jsonrpc",
        "call",
        {
            "service": "object",
            "method": "execute_kw",
            "args": [
                DATABASE,
                uid,
                password,
                "hostel.student",
                "search_read",
                [],  # domain (空列表表示读取所有记录)
                {
                    "fields": fields,
                    "limit": 100,  # 限制返回 100 条记录
                    "order": "id desc",  # 按 ID 降序排列
                }
            ]
        }
    )
    
    return students


def print_students(students):
    """
    格式化打印学生数据
    
    Args:
        students: 学生记录列表
    """
    if not students:
        print("\n没有找到任何学生记录。")
        return
    
    print(f"\n找到 {len(students)} 条学生记录：")
    print("=" * 120)
    
    # 打印表头
    header = f"{'ID':<6} {'姓名':<15} {'性别':<8} {'班级':<15} {'房间':<15} {'宿舍':<15} {'状态':<10} {'入住日期':<12}"
    print(header)
    print("-" * 120)
    
    # 打印每条记录
    for student in students:
        # 处理 Many2one 字段（可能是 [id, name] 格式或 False）
        room_name = student.get('room_id')[1] if student.get('room_id') else "未分配"
        hostel_name = student.get('hostel_id')[1] if student.get('hostel_id') else "未分配"
        
        # 处理性别字段
        gender_map = {
            'male': '男',
            'female': '女',
            'other': '其他'
        }
        gender = gender_map.get(student.get('gender', ''), student.get('gender', ''))
        
        # 处理状态字段
        status_map = {
            'draft': '草稿',
            'reservation': '预订',
            'pending': '待定',
            'paid': '已付款',
            'discharge': '已退房',
            'cancel': '已取消'
        }
        status = status_map.get(student.get('status', ''), student.get('status', ''))
        
        # 处理日期字段
        check_in_date = student.get('check_in_date', '') or ''
        
        # 打印行
        row = (
            f"{student.get('id', ''):<6} "
            f"{student.get('name', ''):<15} "
            f"{gender:<8} "
            f"{student.get('class_id', ''):<15} "
            f"{room_name:<15} "
            f"{hostel_name:<15} "
            f"{status:<10} "
            f"{check_in_date:<12}"
        )
        print(row)
    
    print("=" * 120)


def print_student_details(students):
    """
    打印学生详细信息
    
    Args:
        students: 学生记录列表
    """
    print("\n\n详细信息：")
    print("=" * 80)
    
    for i, student in enumerate(students, 1):
        print(f"\n【学生 {i}】")
        print(f"  ID: {student.get('id')}")
        print(f"  姓名: {student.get('name')}")
        print(f"  性别: {student.get('gender')}")
        print(f"  班级: {student.get('class_id')}")
        
        room_info = student.get('room_id')
        if room_info:
            print(f"  房间: {room_info[1]} (ID: {room_info[0]})")
        else:
            print(f"  房间: 未分配")
        
        hostel_info = student.get('hostel_id')
        if hostel_info:
            print(f"  宿舍: {hostel_info[1]} (ID: {hostel_info[0]})")
        else:
            print(f"  宿舍: 未分配")
        
        print(f"  入住日期: {student.get('check_in_date', '未设置')}")
        print(f"  退房日期: {student.get('check_out_date', '未设置')}")
        print(f"  住宿天数: {student.get('stay_duration', 0)} 天")
        print(f"  状态: {student.get('status')}")
        print(f"  是否激活: {'是' if student.get('active') else '否'}")
        print("-" * 80)


def main():
    """
    主函数
    """
    print("=" * 80)
    print("Odoo JSON-RPC Client - 读取宿舍学生数据")
    print("=" * 80)
    print(f"服务器: {ODOO_URL}")
    print(f"数据库: {DATABASE}")
    print("=" * 80)
    
    try:
        # 1. 身份验证
        uid = authenticate()
        
        # 2. 读取学生数据
        students = search_read_students(uid, API_KEY)
        
        # 3. 打印数据（表格格式）
        print_students(students)
        
        # 4. 打印详细信息
        if students and len(students) > 0:
            # 只打印前5条的详细信息
            print_student_details(students[:5])
            
            if len(students) > 5:
                print(f"\n注意：只显示了前 5 条记录的详细信息，共有 {len(students)} 条记录。")
        
        print("\n✓ 数据读取完成！")
        
    except Exception as e:
        print(f"\n✗ 错误: {str(e)}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    main()

